package com.fary.security.config.annotation;

import com.fary.core.SpringException;

import java.util.concurrent.atomic.AtomicBoolean;

/**
 * 这是一个SecurityBuilder的基类，它可以保证Filter只被创建一次
 */
public abstract class AbstractSecurityBuilder<O> implements SecurityBuilder<O> {

    // 一个原子类型的标志
    private AtomicBoolean building = new AtomicBoolean();

    // 构造器最终船舰的对象，这里创建的其实就是FilterChainProxy
    private O object;

    /**
     * 使用building标志位保证Filter只被创建一次，如果创建成功后再次调用此方法会抛异常。
     * 具体的构造方法是doBuild()，他是一个提供给子类实现的模板方法
     */
    public final O build() throws Exception {
        if (this.building.compareAndSet(false, true)) {
            this.object = doBuild();
            return this.object;
        }
        throw new SpringException("This object has already been built");
    }

    /**
     * 获取被创建的对象（FilterChainProxy），如果没有创建完成就调用该方法会抛异常
     */
    public final O getObject() {
        if (!this.building.get()) {
            throw new IllegalStateException("This object has not been built");
        }
        return this.object;
    }

    /**
     * 供子类实现具体构造逻辑的模板方法
     */
    protected abstract O doBuild() throws Exception;
}